Skip to content

Commit

Permalink
Initial check-in
Browse files Browse the repository at this point in the history
  • Loading branch information
Ray Miller committed May 6, 2010
0 parents commit 88b3c00
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 0 deletions.
7 changes: 7 additions & 0 deletions README
@@ -0,0 +1,7 @@
A handy wrapper around the Text::CSV_XS Perl module for writing CSV
data, taking away some of the boilerplate code for simple usage.

To write to CSV data to STDOUT:

my $csv = CSV::Writer->new;
$csv->write( 'foo', 'bar', 'baz' );
10 changes: 10 additions & 0 deletions dist.ini
@@ -0,0 +1,10 @@
name = CSV-Writer
author = Ray Miller
license = Perl_5
copyright_holder = Ray Miller

[@Classic]

[CompileTests]

[AutoVersion]
120 changes: 120 additions & 0 deletions lib/CSV/Writer.pm
@@ -0,0 +1,120 @@
package CSV::Writer;

# ABSTRACT: wrapper around Text::CSV_XS to reduce boilerplate when writing CSV files

use Moose;
use MooseX::Types::IO 'IO';
use Text::CSV_XS;
use namespace::autoclean;

has output => (
isa => 'IO',
accessor => '_output',
coerce => 1,
default => sub { IO::Handle->new_from_fd( \*STDOUT, 'w' ) }
);

has csv_opts => (
is => 'ro',
isa => 'HashRef',
default => sub { { eol => $/ } }
);

has csv => (
isa => 'Text::CSV_XS',
accessor => '_csv',
lazy_build => 1
);

has columns => (
traits => [ 'Array' ],
handles => {
columns => 'elements',
has_columns => 'count',

},
default => sub { [] },
);

sub _build_csv {
Text::CSV_XS->new( shift->csv_opts );
}

sub write {
my $self = shift;

my $data;

if ( @_ == 1 and ref $_[0] eq 'ARRAY' ) {
$data = shift @_;
}
elsif ( @_ == 1 and ref $_[0] eq 'HASH' ) {
confess "must specify columns when writing a hash"
unless $self->has_columns;
$data = [ @{ $_[0] }{ $self->columns } ];
}
else {
$data = \@_;
}

$self->_csv->print( $self->_output, $data )
or confess "Failed to write data to CSV: $!";
}

1;

__END__
=pod
=head1 NAME
CSV::Writer
=head1 SYNOPSIS
use CSV::Writer;
my $csv = CSV::Writer->new();
$csv->write( @data );
=head1 DESCRIPTION
Wrapper around Text::CSV_XS to reduce boilerplate when writing CSV files.
=head1 METHODS
=head2 new
Constructor, accepts a hash ref or list of key/value pairs:
=over 4
=item output
The filename or L<IO::Handle> object that output will be written to.
=item csv_opts
A hash reference of options for the L<Text::CSV_XS> constructor.
=back
=head2 write( I<@data> )
Write I<@data> as CSV to the output stream
=head1 SEE ALSO
L<Text::CSV_XS>, L<Moose>, L<MooseX::Types::IO>
=head1 AUTHOR
Ray Miller E<lt>rm7@sanger.ac.ukE<gt>
=head1 BUGS
None reported...yet!
=cut
87 changes: 87 additions & 0 deletions t/10-csv-writer.t
@@ -0,0 +1,87 @@
#!/usr/bin/env perl

use strict;
use warnings FATAL => 'all';

use Test::Most;
use File::Temp;
use Readonly;

Readonly my @DATA => (
[ "a", "b,c", "d", 1 ],
[ "e", "f", "g", 2 ],
[ "h", "i", "j", 3 ],
);

Readonly my $CSV => <<'EOT';
a,"b,c",d,1
e,f,g,2
h,i,j,3
EOT

use_ok 'CSV::Writer';

{
ok my $csv = CSV::Writer->new(), 'no args constructor';
isa_ok $csv, 'CSV::Writer', '...the object it returns';
can_ok $csv, 'write';
can_ok $csv, '_output';
isa_ok $csv->_output, 'IO::Handle';
can_ok $csv, '_csv';
isa_ok $csv->_csv, 'Text::CSV_XS';
can_ok $csv, 'csv_opts';
isa_ok $csv->csv_opts, 'HASH';
}

{
my $tmp = File::Temp->new;
ok my $csv = CSV::Writer->new( output => $tmp ), 'output to tmp file';

for ( @DATA ) {
ok $csv->write( $_ ), "print \[@{$_}\]";
}

$tmp->seek(0,0);
my $file_contents = do { local $/ = undef; $tmp->getline };
is $file_contents, $CSV, 'file contents';
}

{
my $csv_str;
ok my $csv = CSV::Writer->new( output => \$csv_str ), 'output to string';
for ( @DATA ) {
ok $csv->write( @$_ ), "print @{$_}";
}

is $csv_str, $CSV, 'string contents';
}

{
my $csv_str;
ok my $csv = CSV::Writer->new( output => \$csv_str, csv_opts => { eol => "\n", quote_char => q{'} } ), 'specify csv options';
for ( @DATA ) {
ok $csv->write( $_ ), "write \[@{$_}\]";
}
( my $expected_str = $CSV ) =~ s/"/'/g;
is $csv_str, $expected_str, 'string contents';
}

{
my $csv_str;
ok my $csv = CSV::Writer->new( output => \$csv_str, columns => [ qw( a b d ) ] ), 'specify columns';
ok $csv->write( { a => 1, b => 2, c => 3, d => 4, e => 5 } ), 'write hashref';
is $csv_str, "1,2,4\n", 'string contents';
}

{
ok my $csv = CSV::Writer->new, 'no options constructor';
throws_ok { $csv->write( { a => 1, b => 2 } ) } qr/must specify columns when writing a hash/;
}

done_testing();






0 comments on commit 88b3c00

Please sign in to comment.