new class ResultSetColumn and tests
Luke Saunders [Fri, 7 Apr 2006 17:29:21 +0000 (17:29 +0000)]
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSetColumn.pm [new file with mode: 0644]
t/basicrels/27result_set_column.t [new file with mode: 0644]
t/helperrels/27result_set_column.t [new file with mode: 0644]
t/run/27result_set_column.tl [new file with mode: 0644]

index c012011..191151f 100644 (file)
@@ -10,6 +10,7 @@ use Data::Page;
 use Storable;
 use Scalar::Util qw/weaken/;
 
+use DBIx::Class::ResultSetColumn;
 use base qw/DBIx::Class/;
 __PACKAGE__->load_components(qw/AccessorGroup/);
 __PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
@@ -414,6 +415,28 @@ sub single {
   return (@data ? $self->_construct_object(@data) : ());
 }
 
+=head2 get_column
+
+=over 4
+
+=item Arguments: $cond?
+
+=item Return Value: $resultsetcolumn
+
+=back
+
+  my $max_length = $rs->get_column('length')->max;
+
+Returns a ResultSetColumn instance for $column based on $self
+
+=cut
+
+sub get_column {
+  my ($self, $column) = @_;
+
+  my $new = DBIx::Class::ResultSetColumn->new($self, $column);
+  return $new;
+}
 
 =head2 search_like
 
diff --git a/lib/DBIx/Class/ResultSetColumn.pm b/lib/DBIx/Class/ResultSetColumn.pm
new file mode 100644 (file)
index 0000000..133e6ff
--- /dev/null
@@ -0,0 +1,184 @@
+package DBIx::Class::ResultSetColumn;
+use strict;
+use warnings;
+use base 'DBIx::Class';
+
+=head1 NAME
+
+  DBIx::Class::ResultSetColumn - helpful methods for messing
+  with a single column of the resultset
+
+=head1 SYNOPSIS
+
+  $rs = $schema->resultset('CD')->search({ artist => 'Tool' });
+  $rs_column = $rs->get_column('year');
+  $max_year = $rs_column->max; #returns latest year
+
+=head1 DESCRIPTION
+
+A convenience class used to perform operations on a specific column of a resultset.
+
+=cut
+
+=head1 METHODS
+
+=head2 new
+
+  my $obj = DBIx::Class::ResultSetColumn->new($rs, $column);
+
+Creates a new resultset column object from the resultset and column passed as params
+
+=cut
+
+sub new {
+  my ($class, $rs, $column) = @_;
+  $class = ref $class if ref $class;
+
+  my $object_ref = { _column => $column,
+                    _parent_resultset => $rs };
+  
+  my $new = bless $object_ref, $class;
+  $new->throw_exception("column must be supplied") unless ($column);
+  return $new;
+}
+
+=head2 next
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: $value
+
+=back
+
+Returns the next value of the column in the resultset (C<undef> is there is none).
+
+Much like $rs->next but just returning the one value
+
+=cut
+
+sub next {
+  my $self = shift;
+    
+  $self->{_resultset} = $self->{_parent_resultset}->search(undef, {select => [$self->{_column}], as => [$self->{_column}]}) unless ($self->{_resultset});
+  my ($row) = $self->{_resultset}->cursor->next;
+  return $row;
+}
+
+=head2 all
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: @values
+
+=back
+
+Returns all values of the column in the resultset (C<undef> is there are none).
+
+Much like $rs->all but returns values rather than row objects
+
+=cut
+
+sub all {
+  my $self = shift;
+  return map {$_->[0]} $self->{_parent_resultset}->search(undef, {select => [$self->{_column}], as => [$self->{_column}]})->cursor->all;
+}
+
+=head2 min
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: $lowest_value
+
+=back
+
+Wrapper for ->func. Returns the lowest value of the column in the resultset (C<undef> is there are none).
+
+=cut
+
+sub min {
+  my $self = shift;
+  return $self->func('MIN');
+}
+
+=head2 max
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: $highest_value
+
+=back
+
+Wrapper for ->func. Returns the highest value of the column in the resultset (C<undef> is there are none).
+
+=cut
+
+sub max {
+  my $self = shift;
+  return $self->func('MAX');
+}
+
+=head2 sum
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: $sum_of_values
+
+=back
+
+Wrapper for ->func. Returns the sum of all the values in the column of the resultset. Use on varchar-like columns at your own risk.
+
+=cut
+
+sub sum {
+  my $self = shift;
+  return $self->func('SUM');
+}
+
+=head2 func
+
+=over 4
+
+=item Arguments: $function
+
+=item Return Value: $function_return_value
+
+=back
+
+Runs a query using the function on the column and returns the value. For example 
+  $rs $schema->resultset("CD")->search({});
+  $rs->get_column('title')->func('LENGTH');
+
+Produces the following SQL
+  SELECT LENGTH( title ) from cd me
+
+=cut
+
+sub func {
+  my $self = shift;
+  my $function = shift;
+
+  my ($row) = $self->{_parent_resultset}->search(undef, {select => {$function => $self->{_column}}, as => [$self->{_column}]})->cursor->next;
+  return $row;
+}
+
+1;
+
+=head1 AUTHORS
+
+Luke Saunders <luke.saunders@gmail.com>
+
+=head1 LICENSE
+
+You may distribute this code under the same terms as Perl itself.
+
+=cut
diff --git a/t/basicrels/27result_set_column.t b/t/basicrels/27result_set_column.t
new file mode 100644 (file)
index 0000000..d8d85be
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use DBICTest::BasicRels;
+
+require "t/run/27result_set_column.tl";
+run_tests(DBICTest->schema);
diff --git a/t/helperrels/27result_set_column.t b/t/helperrels/27result_set_column.t
new file mode 100644 (file)
index 0000000..fd2e13e
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use DBICTest::HelperRels;
+
+require "t/run/27result_set_column.tl";
+run_tests(DBICTest->schema);
diff --git a/t/run/27result_set_column.tl b/t/run/27result_set_column.tl
new file mode 100644 (file)
index 0000000..e62cb62
--- /dev/null
@@ -0,0 +1,23 @@
+sub run_tests {
+my $schema = shift;
+
+plan tests => 5; 
+
+my $rs = $cd = $schema->resultset("CD")->search({});
+
+my $rs_title = $rs->get_column('title');
+my $rs_year = $rs->get_column('year');
+
+is($rs_title->next, 'Spoonful of bees', "next okay");
+
+my @all = $rs_title->all;
+cmp_ok(scalar @all, '==', 5, "five titles returned");
+
+cmp_ok($rs_year->max, '==', 2001, "max okay for year");
+is($rs_title->min, 'Caterwaulin\' Blues', "min okay for title");
+
+cmp_ok($rs_year->sum, '==', 9996, "three artists returned");
+
+}
+
+1;