Fixed typos in HashRefInflator example
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Manual / Cookbook.pod
index ada12c6..ab58aaa 100644 (file)
@@ -387,7 +387,7 @@ From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship
 deep using the same syntax as a multi-step join:
 
   my $rs = $schema->resultset('Tag')->search(
-    undef,
+    {},
     {
       prefetch => {
         cd => 'artist'
@@ -406,6 +406,55 @@ SQL statements:
   my $tag = $rs->first;
   print $tag->cd->artist->name;
 
+=head2 Columns of data
+
+If you want to find the sum of a particular column there are several
+ways, the obvious one is to use search:
+
+  my $rs = $schema->resultset('Items')->search(
+    {},
+    { 
+       select => [ { sum => 'Cost' } ],
+       as     => [ 'total_cost' ],
+    }
+  );
+  my $tc = $rs->first->get_column('total_cost');
+
+Or, you can use the L<DBIx::Class::ResultSetColumn>, which gets
+returned when you ask the C<ResultSet> for a column using
+C<get_column>:
+
+  my $cost = $schema->resultset('Items')->get_column('Cost');
+  my $tc = $cost->sum;
+
+With this you can also do:
+
+  my $minvalue = $cost->min;
+  my $maxvalue = $cost->max;
+
+Or just iterate through the values of this column only:
+
+  while ( my $c = $cost->next ) {
+    print $c;
+  }
+
+  foreach my $c ($cost->all) {
+    print $c;
+  }
+
+C<ResultSetColumn> only has a limited number of built-in functions, if
+you need one that it doesn't have, then you can use the C<func> method
+instead:
+
+  my $avg = $cost->func('AVERAGE');
+
+This will cause the following SQL statement to be run:
+
+  SELECT AVERAGE(Cost) FROM Items me
+
+Which will of course only work if your database supports this function.
+See L<DBIx::Class::ResultSetColumn> for more documentation.
+
 =head2 Using relationships
 
 =head3 Create a new row in a related table
@@ -940,7 +989,7 @@ seperate proxy-class files for this.  We would be copying all the user
 methods into the Admin class.  There is a cleaner way to accomplish
 this.
 
-Overriding the C<inflate_results()> method within the User proxy-class
+Overriding the C<inflate_result> method within the User proxy-class
 gives us the effect we want.  This method is called by
 L<DBIx::Class::ResultSet> when inflating a result from storage.  So we
 grab the object being returned, inspect the values we are looking for,
@@ -1047,4 +1096,54 @@ B<Test File> test.pl
     ### The statement below will print 
     print "I can do admin stuff\n" if $admin->can('do_admin_stuff'); 
 
+=head2 Skip object creation for faster results
+
+DBIx::Class is not built for speed, it's built for convenience and
+ease of use, but sometimes you just need to get the data, and skip the
+fancy objects. Luckily this is also fairly easy using
+C<inflate_result>:
+
+  # Define a class which just returns the results as a hashref:
+  package My::HashRefInflator;
+
+  ## $me is the hashref of cols/data from the immediate resultsource
+  ## $prefetch is a deep hashref of all the data from the prefetched
+  ##   related sources.
+
+  sub mk_hash {
+     my ($me, $rest) = @_;
+
+     return { %$me, 
+        map { ($_ => mk_hash(@{$rest->{$_}})) } keys %$rest
+     };
+  }
+
+  sub inflate_result {
+     my ($self, $source, $me, $prefetch) = @_;
+     return mk_hash($me, $prefetch); 
+  }
+
+  # Change the object inflation to a hashref for just this resultset:
+  $rs->result_class('My::HashRefInflator');
+
+  my $datahashref = $rs->next;
+  foreach my $col (keys %$datahashref) {
+     if(!ref($datahashref->{$col}) {
+        # It's a plain value
+     }
+     elsif(ref($datahashref->{$col} eq 'HASH')) {
+        # It's a related value in a hashref
+     }
+  }
+
+=head2 Want to know if find_or_create found or created a row?
+
+Just use C<find_or_new> instead, then check C<in_storage>:
+
+  my $obj = $rs->find_or_new({ blah => 'blarg' });
+  unless ($obj->in_storage) {
+    $obj->insert;
+    # do whatever else you wanted if it was a new row
+  }
+
 =cut