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

Mailing List Archive: Catalyst: Dev

RFC: Catalyst::View::CSV

 

 

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


travis at ti4tech

Mar 2, 2008, 10:05 PM

Post #1 of 4 (379 views)
Permalink
RFC: Catalyst::View::CSV

I have written a module for producing CSV formatted output as a view. It, of
course, can create any sort of delimited format one desires. Here is the POD
for details.

=head1 NAME

Catalyst::View::CSV - Comma separated values or Delimiter separated values
for your data

=head1 SYNOPSIS

# lib/MyApp/View/CSV.pm
package MyApp::View::CSV;
use base qw( Catalyst::View::CSV );
1;

# lib/MyApp/Controller/SomeController.pm
sub example_action_1 : Local {
my ($self, $c) = @_;

# Array reference of array references.
my $data = [
['col 1','col 2','col ...','col N'], # row 1
['col 1','col 2','col ...','col N'], # row 2
['col 1','col 2','col ...','col N'], # row ...
['col 1','col 2','col ...','col N'] # row N
];

# To output your data in comma seperated values just pass your array by
reference into the 'csv' key of the stash
$c->stash->{'csv'} = $data;

# Finally forward processing to the CSV View
$c->forward('MyApp::View::CSV');
}

# Other ways of storing data
sub example_action_2 : Local {
my ($self, $c) = @_;

# Array of array references
my @data;

push(@data,['col 1','col 2','col ...','col N']); # row 1
push(@data,['col 1','col 2','col ...','col N']); # row 2
push(@data,['col 1','col 2','col ...','col N']); # row ...
push(@data,['col 1','col 2','col ...','col N']); # row N

# OR to produce a single column of data you can simply do the following

my @data = (
'col 1 row 1',
'col 1 row 2',
'col 1 row ...',
'col 1 row N'
);

$c->stash->{'csv'} = \@data;

$c->forward('MyApp::View::CSV');
}

# Available Options to produce other types of delimiter seperated output
sub example_action_3 : Local {
my ($self, $c) = @_;

my $data = [
['col 1','col 2','col ...','col N'], # row 1
['col 1','col 2','col ...','col N'] # row 2
];

# You can change any of the aspects of a delimiter seperated values
format by storing them in the appropriate stash key
# This is an example of tab seperated values for instance

$c->stash->{'quote_char'} = '"'; # default: '"'

$c->stash->{'escape_char'} = '"'; # default: '"'

$c->stash->{'sep_char'} = '\t'; # default: ','

$c->stash->{'eol'} = "\n"; # default: "\n"

$c->stash->{'csv'} = $data;
}

=head1 DESCRIPTION

Catalyst::View::CSV is a Catalyst View handler that returns data in
delimiter seperated values (default is comma) format.

=head1 MIME MEDIA TYPE

If the Content-Type HTTP Header is not set, it will default to 'text/csv'.

# Example of setting your own Content-Type
$c->res->headers->header('Content-Type' => 'text/plain');

# Forward processing to CSV View with a text/plain Content-Type
$c->forward("MyApp::View::CSV");

=head1 OPTIONS

=over 4

=item quote_char

Determines what value will be enclosed within if it contains whitespace or
the delimiter character. DEFAULT: '"'

$c->stash->{'quote_char'} = '/';

=item escape_char

Determines what value will be to escape any delimiter's found in a column.
DEFAULT: '"'

$c->stash->{'escape_char'} = '/';

=item sep_char

Determines the separator between columns. DEFAULT: ','

$c->stash->{'sep_char'} = '|';

=item eol

Any characters defined in eol will be placed at the end of a row. DEFAULT:
'\n'

$c->stash->{'eol'} = '\0';

=item csv

The data that will be processed into delimiter separated values format is
stored here. The data should be an array ref of array refs of scalars or an
array ref of scalars. Note: if nothing is found in csv, the stash is
searched and any array references found will be used as the data instead.

# Array ref of array refs of scalars
my $data = [
['apple','banana','pear'],
['red','yellow','green']
];

$c->stash->{csv} = $data;

# Array ref of scalars
my @data = ('Jan','Feb','Mar','Apr');

$c->stash->{csv} = \@data;

=back

=head1 SUBROUTINES

=over 4

=item process

This method will be called by Catalyst if it is asked to forward to a
component without a specified action.

=item render

Allows others to use this view for much more fine-grained content
generation.

=item _csv

Subroutine that actually produces the delimiter separated values. Intended
to be private in scope to this module.

=back

=head1 AUTHOR

Travis Chase - gaudeon_at_cpan_dot_org

=head1 SEE ALSO

L<Catalyst> L<Text::CSV>

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut


jshirley at gmail

Mar 3, 2008, 9:27 AM

Post #2 of 4 (356 views)
Permalink
Re: RFC: Catalyst::View::CSV [In reply to]

On Sun, Mar 2, 2008 at 10:05 PM, Travis Chase <travis[at]ti4tech.com> wrote:
> I have written a module for producing CSV formatted output as a view. It, of
> course, can create any sort of delimited format one desires. Here is the POD
> for details.
>
> =head1 NAME
>
> Catalyst::View::CSV - Comma separated values or Delimiter separated values
> for your data
>
> =head1 SYNOPSIS
>
> # lib/MyApp/View/CSV.pm
> package MyApp::View::CSV;
> use base qw( Catalyst::View::CSV );
> 1;
>
> # lib/MyApp/Controller/SomeController.pm
> sub example_action_1 : Local {
> my ($self, $c) = @_;
>
> # Array reference of array references.
> my $data = [
> ['col 1','col 2','col ...','col N'], # row 1
> ['col 1','col 2','col ...','col N'], # row 2
> ['col 1','col 2','col ...','col N'], # row ...
> ['col 1','col 2','col ...','col N'] # row N
> ];
>
> # To output your data in comma seperated values just pass your array by
> reference into the 'csv' key of the stash
> $c->stash->{'csv'} = $data;
>
> # Finally forward processing to the CSV View
> $c->forward('MyApp::View::CSV');
> }
>
> # Other ways of storing data
> sub example_action_2 : Local {
> my ($self, $c) = @_;
>
> # Array of array references
> my @data;
>
> push(@data,['col 1','col 2','col ...','col N']); # row 1
> push(@data,['col 1','col 2','col ...','col N']); # row 2
> push(@data,['col 1','col 2','col ...','col N']); # row ...
> push(@data,['col 1','col 2','col ...','col N']); # row N
>
> # OR to produce a single column of data you can simply do the following
> my @data = (
> 'col 1 row 1',
> 'col 1 row 2',
> 'col 1 row ...',
> 'col 1 row N'
> );
>
> $c->stash->{'csv'} = \@data;
>
> $c->forward('MyApp::View::CSV');
> }
>
> # Available Options to produce other types of delimiter seperated output
> sub example_action_3 : Local {
> my ($self, $c) = @_;
>
> my $data = [
> ['col 1','col 2','col ...','col N'], # row 1
> ['col 1','col 2','col ...','col N'] # row 2
> ];
>
> # You can change any of the aspects of a delimiter seperated values
> format by storing them in the appropriate stash key
> # This is an example of tab seperated values for instance
>
> $c->stash->{'quote_char'} = '"'; # default: '"'
>
> $c->stash->{'escape_char'} = '"'; # default: '"'
>
> $c->stash->{'sep_char'} = '\t'; # default: ','
>
> $c->stash->{'eol'} = "\n"; # default: "\n"
>
> $c->stash->{'csv'} = $data;
> }
>
> =head1 DESCRIPTION
>
> Catalyst::View::CSV is a Catalyst View handler that returns data in
> delimiter seperated values (default is comma) format.
>
> =head1 MIME MEDIA TYPE
>
> If the Content-Type HTTP Header is not set, it will default to 'text/csv'.
>
> # Example of setting your own Content-Type
> $c->res->headers->header('Content-Type' => 'text/plain');
>
> # Forward processing to CSV View with a text/plain Content-Type
> $c->forward("MyApp::View::CSV");
>
> =head1 OPTIONS
>
> =over 4
>
> =item quote_char
>
> Determines what value will be enclosed within if it contains whitespace or
> the delimiter character. DEFAULT: '"'
>
> $c->stash->{'quote_char'} = '/';
>
> =item escape_char
>
> Determines what value will be to escape any delimiter's found in a column.
> DEFAULT: '"'
>
> $c->stash->{'escape_char'} = '/';
>
> =item sep_char
>
> Determines the separator between columns. DEFAULT: ','
>
> $c->stash->{'sep_char'} = '|';
>
> =item eol
>
> Any characters defined in eol will be placed at the end of a row. DEFAULT:
> '\n'
>
> $c->stash->{'eol'} = '\0';
>
> =item csv
>
> The data that will be processed into delimiter separated values format is
> stored here. The data should be an array ref of array refs of scalars or an
> array ref of scalars. Note: if nothing is found in csv, the stash is
> searched and any array references found will be used as the data instead.
>
> # Array ref of array refs of scalars
> my $data = [
> ['apple','banana','pear'],
> ['red','yellow','green']
> ];
>
> $c->stash->{csv} = $data;
>
> # Array ref of scalars
> my @data = ('Jan','Feb','Mar','Apr');
>
> $c->stash->{csv} = \@data;
>
> =back
>
> =head1 SUBROUTINES
>
> =over 4
>
> =item process
>
> This method will be called by Catalyst if it is asked to forward to a
> component without a specified action.
>
> =item render
>
> Allows others to use this view for much more fine-grained content
> generation.
>
> =item _csv
>
> Subroutine that actually produces the delimiter separated values. Intended
> to be private in scope to this module.
>
> =back
>
> =head1 AUTHOR
>
> Travis Chase - gaudeon_at_cpan_dot_org
>
> =head1 SEE ALSO
>
> L<Catalyst> L<Text::CSV>
>
> =head1 LICENSE
>
> This library is free software, you can redistribute it and/or modify
> it under the same terms as Perl itself.
>
> =cut
>
> _______________________________________________
> Catalyst-dev mailing list
> Catalyst-dev[at]lists.scsys.co.uk
> http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
>
>

Hey Travis,

It's a good idea that you have there, but it may be better looped into
a larger set of modules. Also, rather than setting a lot of the
config in stash, you should use the module's configuration, like so:

package MyApp::View::CSV;
use base qw(Catalyst::View::CSV);
__PACKAGE__->config(
quote_char => '/'',
'sep_char' => '|',
);

This way you can set sensible defaults in C::V::CSV that are easily
configured on a per-view basis and reduce what has to go into the
stash (and, you can have a configurable stash key as well)

Another idea that I have is an abstraction of serialization formats.
The way I see CSV exporting is a serialization format, much like XLS
would be or even XML and YAML. Catalyst::Action::REST has a good
serialization setup, but it may not be worth factoring that entire
package into your application, and what may prove to be more useful
and reusable is to abstract out the serialization from C::A::REST into
a Catalyst::View::Serialize package and then creating
C::V::Serialize::(XML|CSV|XLS|Dumper|PHP).

This way C::A::REST can use that, and for non-RESTful applications the
serialization can be handled. I tend to always use the REST base
classes, and then I create custom serializers for things like this.

Let me know if you like these thoughts, and we can work together on
getting it going.

-J

--
J. Shirley :: jshirley[at]gmail.com :: Killing two stones with one bird...
http://www.toeat.com

_______________________________________________
Catalyst-dev mailing list
Catalyst-dev[at]lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev


jon at jrock

Mar 3, 2008, 10:10 AM

Post #3 of 4 (368 views)
Permalink
Re: RFC: Catalyst::View::CSV [In reply to]

* On Mon, Mar 03 2008, Travis Chase wrote:
> I have written a module for producing CSV formatted output as a view. It, of
> course, can create any sort of delimited format one desires. Here is the POD
> for details.

I have a feeling that this has been done before.

> $c->stash->{'quote_char'} = '"'; # default: '"'
>
> $c->stash->{'escape_char'} = '"'; # default: '"'
>
> $c->stash->{'sep_char'} = '\t'; # default: ','
>
> $c->stash->{'eol'} = "\n"; # default: "\n"
>
> $c->stash->{'csv'} = $data;

I think all this stuff should be per-class, not per-request. If you
need different settings, create another subclass with different
configuration. Much cleaner.

Regards,
Jonathan Rockway

_______________________________________________
Catalyst-dev mailing list
Catalyst-dev[at]lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev


travis at ti4tech

Mar 5, 2008, 10:27 AM

Post #4 of 4 (346 views)
Permalink
Re: RFC: Catalyst::View::CSV [In reply to]

J. Shirley and Jonathan Rockway

Thanks for both of your responses. Your comments helped me see I wasn't
quite getting to the intent of my contribution so I am going to scrap
Catalyst::View::CSV in favor of Catalyst::View::Download. The CSV module
with the improvements to config you both suggested will be included as
Catalyst::View::Download::CSV. Shortly after this message I will be sending
an RFC for that module. I would again greatly appreciate your comments about
that module as I think it better defines what I am really trying to
accomplish.

Thanks,

- Travis

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


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.